//
// Created on 2024/4/25.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".


#include <stdint.h>

#ifndef TRUE
#define TRUE 1
#define FALSE 0 
#endif

#define RTMP_MAX_HEADER_SIZE 18

#define RTMP_PACKET_SIZE_LARGE 0
#define RTMP_PACKET_SIZE_MEDIUM 1
#define RTMP_PACKET_SIZE_SMALL 2
#define RTMP_PACKET_SIZE_MINIMUM 3


/*      RTMP_PACKET_TYPE_...                0x00 */
#define RTMP_PACKET_TYPE_CHUNK_SIZE 0x01
/*      RTMP_PACKET_TYPE_...                0x02 */
#define RTMP_PACKET_TYPE_BYTES_READ_REPORT 0x03
#define RTMP_PACKET_TYPE_CONTROL 0x04
#define RTMP_PACKET_TYPE_SERVER_BW 0x05
#define RTMP_PACKET_TYPE_CLIENT_BW 0x06
/*      RTMP_PACKET_TYPE_...                0x07 */
#define RTMP_PACKET_TYPE_AUDIO 0x08
#define RTMP_PACKET_TYPE_VIDEO 0x09
/*      RTMP_PACKET_TYPE_...                0x0A */
/*      RTMP_PACKET_TYPE_...                0x0B */
/*      RTMP_PACKET_TYPE_...                0x0C */
/*      RTMP_PACKET_TYPE_...                0x0D */
/*      RTMP_PACKET_TYPE_...                0x0E */
#define RTMP_PACKET_TYPE_FLEX_STREAM_SEND 0x0F
#define RTMP_PACKET_TYPE_FLEX_SHARED_OBJECT 0x10
#define RTMP_PACKET_TYPE_FLEX_MESSAGE 0x11
#define RTMP_PACKET_TYPE_INFO 0x12
#define RTMP_PACKET_TYPE_SHARED_OBJECT 0x13
#define RTMP_PACKET_TYPE_INVOKE 0x14
/*      RTMP_PACKET_TYPE_...                0x15 */
#define RTMP_PACKET_TYPE_FLASH_VIDEO 0x16

typedef enum {
    AMF_NUMBER = 0,
    AMF_BOOLEAN,
    AMF_STRING,
    AMF_OBJECT,
    AMF_MOVIECLIP, /* reserved, not used */
    AMF_NULL,
    AMF_UNDEFINED,
    AMF_REFERENCE,
    AMF_ECMA_ARRAY,
    AMF_OBJECT_END,
    AMF_STRICT_ARRAY,
    AMF_DATE,
    AMF_LONG_STRING,
    AMF_UNSUPPORTED,
    AMF_RECORDSET,  /*  reserved, not used */
    AMF_XML_DOC,
    AMF_TYPED_OBJECT,
    AMF_AVMPLUS, /* switch to AMF3 */
    AMF_INVALID = 0xff
} AMFDataType;

typedef struct RTMPChunk {
    int c_headerSize;
    int c_chunkSize;
    char *c_chunk;
    char c_header[RTMP_MAX_HEADER_SIZE];
} RTMPChunk;

typedef struct AVal {
    char *av_val;
    int av_len;
} AVal;

typedef struct RTMP_METHOD {
    AVal name;
    int num;
} RTMP_METHOD;

typedef struct RTMPPacket {
    uint8_t m_headerType;
    uint8_t m_packetType;
    uint8_t m_hasAbsTimestamp; /* timestamp absolute or relative? */
    int m_nChannel;
    uint32_t m_nTimeStamp; /* timestamp */
    int32_t m_nInfoField2; /* last 4 bytes in a long header */
    uint32_t m_nBodySize;
    uint32_t m_nBytesRead;
    RTMPChunk *m_chunk;
    char *m_body;
} RTMPPacket;

typedef struct RTMP_READ {
    char *buf;
    char *bufpos;
    unsigned int buflen;
    uint32_t timestamp;
    uint8_t dataType;
    uint8_t flags;
#define RTMP_READ_HEADER 0x01
#define RTMP_READ_RESUME 0x02
#define RTMP_READ_NO_IGNORE 4
#define RTMP_READ_GOTKF 8
#define RTMP_READ_GOTFLVK x10
#define RTMP_READ_SEEKING x20
    int8_t status;
#define RTMP_READ_COMPLETE 
#define RTMP_READ_ERROR 
#define RTMP_READ_EOF 1
#define RTMP_READ_IGNORE 0

    /* if bResume == TRUE */
    uint8_t initialFrameType;
    uint32_t nResumeTS;
    char *metaHeader;
    char *initialFrame;
    uint32_t nMetaHeaderSize;
    uint32_t nInitialFrameSize;
    uint32_t nIgnoredFrameCounter;
    uint32_t nIgnoredFlvFrameCounter;
} RTMP_READ;

#define RTMP_BUFFER_CACHE_SIZE (16 * 1024)

typedef struct RTMPSockBuf {
    int sb_socket;
    int sb_size;                         /* number of unprocessed bytes in buffer */
    char *sb_start;                    /*   pointer into sb_pBuffer of next byte to process */
    char sb_buf[RTMP_BUFFER_CACHE_SIZE]; /* data read from socket */
    int sb_timedout;
    void *sb_ssl;
} RTMPSockBuf;

typedef struct AMFObject {
    int o_num;
    struct AMFObjectProperty *o_props;
} AMFObject;

typedef struct AMFObjectProperty {
    AVal p_name;
    AMFDataType p_type;
    union {
        double p_number;
        AVal p_aval;
        AMFObject p_object;
    } p_vu;
    int16_t p_UTCoffset;
} AMFObjectProperty;


typedef struct RTMP_LNK {
    AVal hostname;
    AVal sockshost;

    AVal playpath0; /* parsed from URL */
    AVal playpath;  /* passed in explicitly */
    AVal tcUrl;
    AVal swfUrl;
    AVal pageUrl;
    AVal app;
    AVal auth;
    AVal flashVer;
    AVal subscribepath;
    AVal usherToken;
    AVal token;
    AVal pubUser;
    AVal pubPasswd;
    AMFObject extras;
    int edepth;

    int seekTime;
    int stopTime;

#define RTMP_LF_AUTH 0x0001  using auth param */
#define RTMP_LF_LIVE 0x0002  stream is live */
#define RTMP_LF_SWFV 0x0004  do SWF verification */
#define RTMP_LF_PLST 0x0008  send playlist before play */
#define RTMP_LF_BUFX 0x0010  toggle stream on BufferEmpty msg */
#define RTMP_LF_FTCU 0x0020  free tcUrl on close */
    int lFlags;

    int swfAge;

    int protocol;
    int timeout; /* connection timeout in seconds */

#define RTMP_PUB_NAME 0x0001  /* send login to server */
#define RTMP_PUB_RESP 0x0002  /* send salted password hash */
#define RTMP_PUB_ALLOC 0x0004 /* allocated data for new tcUrl & app */
#define RTMP_PUB_CLEAN 0x0008 /* need to free allocated data for newer tcUrl & app at exit */
#define RTMP_PUB_CLATE 0x0010 /* late clean tcUrl & app at exit */
    int pFlags;

    unsigned short socksport;
    unsigned short port;

#ifdef CRYPTO
#define RTMP_SWF_HASHLEN 32
    void *dh; * for encryption */
    void *rc4keyIn;
    void *rc4keyOut;

    uint32_t SWFSize;
    uint8_t SWFHash[RTMP_SWF_HASHLEN];
    char SWFVerificationResponse[RTMP_SWF_HASHLEN + 10];
#endif
} RTMP_LNK;

typedef struct RTMP {
    int m_inChunkSize;
    int m_outChunkSize;
    int m_nBWCheckCounter;
    int m_nBytesIn;
    int m_nBytesInSent;
    int m_nBufferMS;
    int m_stream_id; /* returned in _result from createStream */
    int m_mediaChannel;
    uint32_t m_mediaStamp;
    uint32_t m_pauseStamp;
    int m_pausing;
    int m_nServerBW;
    int m_nClientBW;
    uint8_t m_nClientBW2;
    uint8_t m_bPlaying;
    uint8_t m_bSendEncoding;
    uint8_t m_bSendCounter;

    int m_numInvokes;
    int m_numCalls;
    RTMP_METHOD *m_methodCalls;/*  remote method calls queue */

    int m_channelsAllocatedIn;
    int m_channelsAllocatedOut;
    RTMPPacket **m_vecChannelsIn;
    RTMPPacket **m_vecChannelsOut;
    int *m_channelTimestamp; /* abs timestamp of last packet */

    double m_fAudioCodecs;/*   audioCodecs for the connect packet */
    double m_fVideoCodecs;/*   videoCodecs for the connect packet */
    double m_fEncoding; /*    AMF0 or AMF3 */

    double m_fDuration;/*  duration of stream in seconds */

    int m_msgCounter;/*   RTMPT stuff */
    int m_polling;
    int m_resplen;
    int m_unackd;
    AVal m_clientID;

    RTMP_READ m_read;
    RTMPPacket m_write;
    RTMPSockBuf m_sb;
    RTMP_LNK Link;
    // lake
    char ipaddr[16];
} RTMP;

